package pl.druminski.robinhood.controller;

import java.io.FileOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import pl.druminski.robinhood.model.Data;
import pl.druminski.robinhood.plugininterface.InterfaceVersion;
import pl.druminski.robinhood.plugininterface.Plugin;

/**
 * @author Łukasz Drumiński
 * 
 */
public class Updating
{

    private Data data;
    private DocumentBuilderFactory factory;
    private DocumentBuilder builder;
    private Document doc;
    private Document docNews;
    private Element rootNews;
    private Plugin [] plugins;

    public Updating(Data data)
    {
        this.data = data;

        factory = DocumentBuilderFactory.newInstance();
        try
        {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException ex)
        {
            Logger.getLogger(data.getLogName()).warning("Problem z parserem xml. " + ex.getMessage());
        }

        docNews = builder.newDocument();
        rootNews = docNews.createElement("root");
        docNews.appendChild(rootNews);


    }

    private void createElementUpdate(String url, String dest)
    {
        Element element = docNews.createElement("update");
        Element childUrl = docNews.createElement("url");
        Element childDest = docNews.createElement("dest");
        childUrl.setTextContent(url);
        childDest.setTextContent(dest);
        element.appendChild(childUrl);
        element.appendChild(childDest);

        rootNews.appendChild(element);

    }

    private boolean verifyPlugin(String pluginName, String url, Double version)
    {
        boolean newPlugin = true;
        boolean update = false;

        //odszukaj pluginu w dostpenych pluginach i pobierz jego wersje
        for(int i=0; i < plugins.length; i++)
        {
            //jesli uzytkownik posiada stara wersje pluginu, to dodaj plugin do aktualizacji
            if (plugins[i].getName().toLowerCase().equals(pluginName.toLowerCase()))
            {
                newPlugin = false;
                if (version > plugins[i].getVersion())
                {
                    update = true;
                    createElementUpdate(url, data.getDirPluginName());

                }
                break;
            }
        }

        //jesli uzytkownik nie posiada tego pluginu, to dodaj plugin do listy pobieranych elementow
        if (newPlugin)
        {
            update = true;
            createElementUpdate(url, data.getDirPluginName());
        }

        return update;
    }

    public boolean CheckForUpdates(Plugin[] plugins)
    {
        boolean update = false;
        double version;
        String url;
        String pluginName=null;

        this.plugins = plugins;

        try
        {
            doc = builder.parse(data.getInfoAddress().openStream());
        } catch (Exception ex)
        {
            Logger.getLogger(data.getLogName()).warning("Problem z parserem xml. " + ex.getMessage());
        }

        Element root = doc.getDocumentElement();

        NodeList children = root.getChildNodes();

        for (int i = 0; i < children.getLength(); i++)
        {
            Node child = children.item(i);

            if (child instanceof Element)
            {
                String name = child.getNodeName();
                version = 0;
                url = "";

                if (name.equals("robinHood") || name.equals("pluginInterface"))
                {
                    NodeList childs = child.getChildNodes();
                    for (int j = 0; j < childs.getLength(); j++)
                    {
                        child = childs.item(j);
                        if (child instanceof Element)
                        {
                            if (child.getNodeName().equals("version"))
                            {
                                version = Double.parseDouble(child.getFirstChild().getTextContent());
                            } else if (child.getNodeName().equals("url"))
                            {
                                url = child.getFirstChild().getTextContent();
                            }
                        }
                    }
                }

                if (name.equals("robinHood"))
                {
                    if (data.getVersion() < version)
                    {
                        update = true;
                        createElementUpdate(url, "." + data.getSeparator());
                    }
                } else if (name.equals("pluginInterface"))
                {
                    if (InterfaceVersion.getVersion() < version)
                    {
                        update = true;
                        createElementUpdate(url, data.getLibPath());
                    }
                } else if (name.equals("plugins"))
                {
                    NodeList childs = child.getChildNodes();
                    for (int j = 0; j < childs.getLength(); j++)
                    {
                        child = childs.item(j);
                        if (child.getNodeName().equals("plugin"))
                        {
                            NodeList childChild = child.getChildNodes();
                            for (int k = 0; k < childChild.getLength(); k++)
                            {
                                child = childChild.item(k);
                                if (child instanceof Element)
                                {
                                    if (child.getNodeName().equals("version"))
                                    {
                                        version = Double.parseDouble(child.getFirstChild().getTextContent());
                                        
                                    }
                                    else if (child.getNodeName().equals("url"))
                                    {
                                        url = child.getFirstChild().getTextContent();
                                    }
                                    else if (child.getNodeName().equals("name"))
                                    {
                                        pluginName = child.getFirstChild().getTextContent();
                                        
                                    }
                                }
                            }

                            if (verifyPlugin(pluginName, url, version))
                            {
                                update = true;
                            }

                        }
                    }

                    //TODO ladowanie innych plikow

                }
            }

        }

        if (update)
        {
            try
            {
                //utworz plik xml z informacjami o elementach do pobrania
                Transformer t = TransformerFactory.newInstance().newTransformer();
                t.setOutputProperty(OutputKeys.METHOD, "xml");
                t.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
                t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
                t.setOutputProperty(OutputKeys.INDENT, "yes");
                t.transform(new DOMSource(docNews), new StreamResult(new FileOutputStream(data.getUpdateFile())));

            } catch (Exception ex)
            {
                Logger.getLogger(data.getLogName()).log(Level.SEVERE, null, ex);
            }

        }

        return update;
    }
}
